

/////////////////////////////////////////////////////////////////////////////////////////
//
// Licensed is under the "New" BSD License.
//		License page - https://code.google.com/p/motioncodelibrary/wiki/LICENSE
//
// MotionCodeLibrary collection - https://code.google.com/p/motioncodelibrary/
//
// Author Sergey Solohin (Neill3d) 2014
//  e-mail to: s@neill3d.com
//		www.neill3d.com
/////////////////////////////////////////////////////////////////////////////////////////

#pragma		once

//--- SDK include
#include <fbsdk/fbsdk.h>
#include "math3d.h"

#define	VIEWPORT_HIT_RANGE		3

//! collect data about a viewport, camera and view plane
class	Viewport
{
public:
	//! a constructor
	Viewport();

	//! ScreenToSpace
	/*!
		convert screen cursor coords to world 3d space position

		\param sX - mouse x
		\param sY - mouse y
		\param height - window height
		\return world 3d vector
	*/
	FBVector3d ScreenToSpace( int sX, int sY, int height );

	//! SpaceToScreen
	/*!
		convert world 3d pos to screen one

		\param v - world point pos
		\return screen point pos
	*/
	FBVector3d SpaceToScreen( const FBVector3d	&v );

	//! ScreenToSpaceRay
	/*!
		convert screen cursor coords to world 3d space position

		\param sX - mouse x
		\param sY - mouse y
		\param height - window height
		\param	start - ray start position (return)
		\param	end - ray end position (return)
	*/
	void ScreenToSpaceRay( int sX, int sY, int height, FBVector3d &start, FBVector3d &end );

	//! HitPoints
	/*!
		hit points with mouse pick

		\param	selState - selection state flags for each point
		\return - number of selected points
	*/
	int HitPoints(int X, int Y, FBArrayTemplate<FBVector3d> &points, FBArrayTemplate<bool>	&selState);
	int HitPoints(int X, int Y, FBArrayTemplate<FBVector3d> &points, int hitrange = VIEWPORT_HIT_RANGE);		// return only one top point

	//! HitPoints
	/*!
		hit points with selection rect

		\param	selState - selection state flags for each point
		\return - number of selected points
	*/
	int HitPoints(int X, int Y, int X2, int Y2, FBArrayTemplate<FBVector3d> &points, FBArrayTemplate<bool>	&selState);

	//! Update
	/*!
		update viewport

		\param currentCamera - current viewport camera (manipulator variable)
	*/
	void Update(HFBCamera	currentCamera);

	//! viewport height
	double getHeight();
	double getWidth();
	double getFOV();
	double getNear();

	//! return calculated viewplane
	FBVector4d	getViewPlane();

	//! draw debug lines
	void Draw();

private:
	GLint	lViewport[4];
	FBMatrix	modelview;
	FBMatrix	projection;

	//! perspective or ortho projection
	bool				mPerspective;
	bool				mSystem; //! user camera or default views
	FBVector3d		mCamera;
	FBVector3d		mInterest;	//! importang to have camera target
	int				mScreenWidth;
	int				mScreenHeight;
	double			mFOV;
	double			mNearDist;
	double			mFarDist;

	FBVector4d		mViewPlane;
	FBVector3d		mViewRight;
	FBVector3d		mViewUp;

	//! calc viewplane for current camera
	void BuildViewPlane();
	// sort selection by depth
	int GetTopPoint(FBArrayTemplate<FBVector3d> &points, FBArrayTemplate<bool>	&selState);
};
